package org.correct.link;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.correct.model.PageInfoItem;
import org.correct.util.PageInfoAccessor;

public class LinkParser {
	
	private class InList {
		private LinkedList<Integer> inList;
		
		public InList() {
			inList = new LinkedList<Integer>();
		}
		
		public void add(Integer i) {
			inList.add(i);
		}
		
		public LinkedList<Integer> getList() {
			return this.inList;
		}
	}
	
	private HashMap<String, Integer> urlTable;
	private String[] urlForId;
	private InList[] inList;
	private int maxId;
	
	public LinkParser() {
		urlTable = new HashMap<String, Integer>();
	}
	
	public void loadPageInfo(String fileName) {
		maxId = 0;
		List<PageInfoItem> pageList = new PageInfoAccessor(fileName).getPageInfoItems();
		for(PageInfoItem page : pageList) {
			urlTable.put(page.url, page.id);
			if(page.id > maxId)
				maxId = page.id;
		}
		
		urlForId = new String[maxId + 1];
		for(PageInfoItem page : pageList) {
			urlForId[page.id] = page.url;
		}
		
		inList = new InList[maxId + 1];
		for(int i = 0; i < maxId + 1; i++) {
			if(urlForId[i] != null)
				inList[i] = new InList();
		}
	}
	
	public void parseLinks(String htmlDir) {
		File dir = new File(htmlDir);
		
		File[] flist = dir.listFiles();
		
		for(int i = 0; i < flist.length; i++)
			getOutLinks(flist[i]);
	}
	
	private void getOutLinks(File f) {
		String fileName = f.getName();
		int iDot = fileName.indexOf('.');
		int id = 0;
		if(iDot == -1)
			id = Integer.parseInt(fileName);
		else
			id = Integer.parseInt(fileName.substring(0, fileName.indexOf('.')));
		
		if(id > maxId)
			return;
		
		String url = urlForId[id];
		if(url == null)
			return;
		
		BufferedReader r;
		StringBuffer buf = new StringBuffer();
		try {
			r = new BufferedReader(new FileReader(f));
			
			String line = null;
			while((line = r.readLine()) != null) {
				buf.append(line + "\n");
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String html = buf.toString();
		
		Pattern pattern = Pattern.compile("<[aA] href ?= ?\"(.+?)\"");
		Matcher matcher = pattern.matcher(html);
		String nextUrl = null;
		
		int iSharp = 0;
		int iSlash = 0;
		Integer urlId = null;
		
		while(matcher.find()) {
			nextUrl = matcher.group(1);
			
			// trim anchors
			iSharp = nextUrl.lastIndexOf("#");
			if(iSharp >= 0)
				nextUrl = nextUrl.substring(0, nextUrl.lastIndexOf("#"));

			// trace relative URL's
			if(!(nextUrl.startsWith("http://") || nextUrl.startsWith("https://"))) {
				iSlash = url.lastIndexOf("/");
				if(iSlash > 0)
					nextUrl = url.substring(0, iSlash) +
						(nextUrl.startsWith("/") ? nextUrl : ("/" + nextUrl));
				else
					nextUrl = url + (nextUrl.startsWith("/") ? nextUrl : ("/" + nextUrl));
			}
			
			urlId = urlTable.get(nextUrl);
			if(urlId != null)
				inList[urlId].add(id);
		}
	}
	
	public void generageLinkFile(String outFile) {
		try {
			PrintWriter w = new PrintWriter(outFile);
			for(int i = 0; i < inList.length; i++) {
				if(inList[i] != null) {
					w.print(i);
					for(Integer j : inList[i].getList()) {
						w.print(" " + j);
					}
					w.println();
				}
			}
			
			w.flush();
			w.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String args[]) {
		LinkParser p = new LinkParser();
		p.loadPageInfo("page-info.txt");
		p.parseLinks("html");
		p.generageLinkFile("inlinks");
	}
}
